#include "fixit_proc.hpp"
#include "zutils.hpp"
#include <assert.h>
#include <cstdio>
#include <sstream>
#include <algorithm>

namespace fix
{

	static const utl::conn::ProxyData_t proxy = {"proxymci.telefonicasoluciones.com", "tsoluciones@tsol", "soluciones", 8080};
	static const char* const dbtv_apiKey = "9F336A439F44A48B";
	static const char* const dbtv_urlBase = "http://thetvdb.com/api/";
	static const char* const dbtv_urlBaseWitKey = "http://thetvdb.com/api/9F336A439F44A48B/";
	static const char* const dbtv_urlTime = "http://thetvdb.com/api/Updates.php?type=none";	
	static const char* const dbtv_getSeries = "http://thetvdb.com/api/GetSeries.php?seriesname=";


	void CheckNombreSerie(const char* const nombreSerie, const char* const idioma, std::vector<std::pair<std::string, std::string> >& Resultados)
	{
		std::string XMLContent;
		std::string url;	
		url = dbtv_getSeries;
		url.append("%27");
		url.append(nombreSerie);
		utl::rgx::RemplaceAll("\\s", url.c_str(), "%20", url);
		url.append("%27");
		url.append("&language=");
		url.append(idioma);
        #ifdef _MSC_VER
		utl::conn::GetByHttpInCharset(url.c_str(), &proxy, "UTF-8", "WINDOWS-1252", XMLContent);
        #else
        utl::conn::GetByHttp(url.c_str(), NULL, XMLContent);		
        #endif
		utl::xml::vDataPairs_t vDataPairs;
		utl::xml::Childs_t childsNames, pathToTarget;
		utl::str::loadVectorOfStrings(childsNames, "SeriesName", "seriesid");
		utl::str::loadVectorOfStrings(pathToTarget, "Data", "Series");
		utl::xml::GetDataFromLevelN(XMLContent.c_str(), childsNames, pathToTarget, vDataPairs);
		for(utl::xml::vDataPairs_t::const_iterator it = vDataPairs.begin(); it != vDataPairs.end(); it++)
		{
			Resultados.push_back(std::make_pair(utl::xml::GetChildValue(*it, "SeriesName"), utl::xml::GetChildValue(*it, "seriesid")));
		}
	}

	static size_t str2uint(const char* const cadena)
	{
		std::stringstream ss;
		size_t val = 0;
		ss << cadena;
		ss >> val;
		return val;
	}

	static void convSeas_Epi(const char* season, const char* episode, size_t& Season, size_t& Episodie )
	{		
		Season = str2uint(season); 
		Episodie = str2uint(episode);		
	}

	std::pair<bool, std::string> RenameFiles(const std::vector<SortSeries_t>& sortSeries)
	{
		if (sortSeries.empty())
			return std::make_pair(false, "ERROR: Sin ficheros a renombrar, asegurese de haber ejecutado el procesado de series.");
		std::stringstream ssCmd;
		int res = 0;
		if (!system(NULL))
			return std::make_pair(false, "ERROR: El sistema no puede ejecutar comandos.");
		for(std::vector<SortSeries_t>::const_iterator it = sortSeries.begin(); it != sortSeries.end(); it++)
		{
			if (it->TitleNEW.compare(it->TitleORG) == 0)
				continue;
			#ifdef _MSC_VER
			ssCmd << "rename ";
			#else
			ssCmd << "mv ";
			#endif
			ssCmd << "\"" << it->Path << it->TitleNEW << "\" ";
			ssCmd << "\"" << it->Path << it->TitleORG << ".avi\"";
			res = 0;
			res = system(ssCmd.str().c_str());			
			if (res)
				return std::make_pair(false, "ERROR: El renombrado ha fallado en : " + ssCmd.str());
			ssCmd.str("");
		}
		return std::make_pair(true, "Todos los ficheros renombrados correctamente");
	}

	bool ProcSeries(const char* const path, const char* const idSerie, const char* const Serie, const char* const idioma,
					const char* const patron, std::vector<SortSeries_t>& sortSeries, std::string& DespError)
	{
		std::string LangKeyZIP(idioma), LangKeyXML(idioma);
		LangKeyZIP.append(".zip");
		LangKeyXML.append(".xml");
		std::string url(dbtv_urlBaseWitKey);
		url.append("series/");
		url.append(idSerie);
		url.append("/all/");
		url.append(LangKeyZIP);
        #ifdef _MSC_VER
		const char* const TPATH = "C:\\Windows\\Temp\\";
        #else
        const char* const TPATH = "/var/tmp/";
        #endif
		std::string Tpath(TPATH);
		Tpath.append(idSerie);		
		Tpath.append(LangKeyZIP);		
		
		std::string XMLContent;
        #ifdef _MSC_VER
		if (utl::io::ZipReadinCharset(Tpath.c_str(), LangKeyXML.c_str(), "UTF-8", "WINDOWS-1252", XMLContent) == false)
        #else
        if (utl::io::ZipRead(Tpath.c_str(), LangKeyXML.c_str(), XMLContent) == false)
        #endif
		{
            #ifdef _MSC_VER
			utl::conn::GetHttpFile(url.c_str(), Tpath.c_str(), &proxy);
            #else
            utl::conn::GetHttpFile(url.c_str(), Tpath.c_str(), NULL);
            #endif
            #ifdef _MSC_VER
            if (utl::io::ZipReadinCharset(Tpath.c_str(), LangKeyXML.c_str(), "UTF-8", "WINDOWS-1252", XMLContent) == false)
            #else
            if (utl::io::ZipRead(Tpath.c_str(), LangKeyXML.c_str(), XMLContent) == false)
            #endif
			{
				DespError = "No se han recuperado datos de http://thetvdb.com o el fichero ZIP esta incompleto.";
				return false;
			}
		}


		utl::xml::vDataPairs_t vDataPairs;
		utl::xml::Childs_t childsNames, pathToTarget;
		utl::str::loadVectorOfStrings(childsNames, "SeasonNumber", "EpisodeNumber", "EpisodeName");
		utl::str::loadVectorOfStrings(pathToTarget, "Data", "Episode");
		utl::xml::GetDataFromLevelN(XMLContent.c_str(), childsNames, pathToTarget, vDataPairs);
		if (vDataPairs.empty())
		{
			DespError = "Ha habido un error en la conversion del XML.";
			return false;
		}
		XMLContent.clear();

		
		std::string fileContent;
        #ifdef _MSC_VER
		utl::io::FileReadBinInCharset(path, "UTF-8", "WINDOWS-1252", fileContent);
        #else
        utl::io::FileReadBin(path, fileContent);
        #endif
		std::vector<std::string> lines;
		utl::str::SplitByChar(fileContent.c_str(), '\n', lines);
		if (fileContent.empty())
		{
			DespError = "No se han recuperado datos del fichero que contiene la series a procesar.";
			return false;
		}
		fileContent.clear();
		std::vector<std::string> rgxResult, rgxMY;
		std::stringstream ss;
		std::string sSeason, sEpisode, FilePath, FileName;
		char SeasionEpisode[10];
		for(std::vector<std::string>::iterator it = lines.begin(); it != lines.end(); it++)
		{
			FilePath = it->substr(0, it->find_last_of("/")+1);
			FileName = it->substr(it->find_last_of("/")+1, it->size());

			utl::rgx::FindAll(patron, FileName.c_str(), rgxResult);
			utl::rgx::FindAll("(\\d+)", rgxResult[0].c_str(), rgxMY);			
			if (rgxMY.size() == 0)
			{
				sortSeries.push_back( SortSeries_t(0, 0, "ERROR: NO SE HA PODIDO CONVERTIR", FileName.c_str(), FilePath.c_str()) );
				rgxResult.clear();
				rgxMY.clear();
				continue;
			} 
			else if (rgxMY.size() == 1)
			{
				std::string tmp = rgxMY[0];
				rgxMY.clear();
				if (tmp.size() == 4)
				{
					rgxMY.push_back(tmp.substr(0, 2));
					rgxMY.push_back(tmp.substr(2, 2));
				}
				else if (tmp.size() == 3)
				{
					rgxMY.push_back(tmp.substr(0, 1));
					rgxMY.push_back(tmp.substr(1, 2));
				}
				else
				{
					sortSeries.push_back( SortSeries_t(0, 0, "ERROR: NO SE HA PODIDO CONVERTIR", FileName.c_str(), FilePath.c_str()) );
					rgxResult.clear();
					rgxMY.clear();
					continue;
				}
			}
			rgxResult.clear();
			size_t SeasonORG = 0, EpisodeORG = 0, SeasonNEW = 0, EpisodeNEW = 0;
			convSeas_Epi(rgxMY[0].c_str(), rgxMY[1].c_str(), SeasonORG, EpisodeORG);
			rgxMY.clear();
			
			for(utl::xml::vDataPairs_t::const_iterator itv = vDataPairs.begin(); itv != vDataPairs.end(); itv++)
			{
				sSeason = utl::xml::GetChildValue(*itv, "SeasonNumber");
				sEpisode = utl::xml::GetChildValue(*itv, "EpisodeNumber");
				convSeas_Epi(sSeason.c_str(), sEpisode.c_str(), SeasonNEW, EpisodeNEW);
				if (SeasonNEW == SeasonORG && EpisodeNEW == EpisodeORG)
				{
					memset(&SeasionEpisode[0], 0, 10);
					sprintf(SeasionEpisode, "%02dx%02d", SeasonNEW, EpisodeNEW);
					ss << Serie << " " << SeasionEpisode << " - " << utl::xml::GetChildValue(*itv, "EpisodeName");
					sortSeries.push_back( SortSeries_t(SeasonNEW, EpisodeNEW, ss.str(), FileName, FilePath) );
					ss.str("");
				}
				sSeason.clear();
				sEpisode.clear();
			}
			FilePath.clear();
			FileName.clear();
		}
		std::sort(sortSeries.begin(), sortSeries.end());

		return true;
	}

}

